home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / source / graphicgems4.lha / GemsIV / ray_cyl.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-06  |  6.0 KB  |  193 lines

  1. /*
  2.  * ANSI C code from the article
  3.  * "Intersecting a Ray with a Cylinder"
  4.  * by Joseph M. Cychosz and Warren N. Waggenspack, Jr.,
  5.  * (3ksnn64@ecn.purdue.edu, mewagg@mewnw.dnet.lsu.edu)
  6.  * in "Graphics Gems IV", Academic Press, 1994
  7.  */
  8.  
  9. #include    "GraphicsGems.h"
  10. #include    <math.h>
  11.  
  12. /* ---- intcyl - Intersect a ray with a cylinder. --------------------- */
  13. /*                                    */
  14. /*                                    */
  15. /*    Description:                            */
  16. /*        Intcyl determines the intersection of a ray with a        */
  17. /*        cylinder.                            */
  18. /*                                    */
  19. /*    On entry:                            */
  20. /*        raybase = The base point of the intersecting ray.        */
  21. /*        raycos  = The direction cosines of the above ray. (unit)    */
  22. /*        base    = The base location of the cylinder.        */
  23. /*        axis    = The axis of symmetry for the cylinder.  (unit)    */
  24. /*        radius  = The radius of the cylinder.            */
  25. /*                                    */
  26. /*    On return:                            */
  27. /*        in        = The entering distance of the intersection.    */
  28. /*        out        = The leaving  distance of the intersection.    */
  29. /*                                    */
  30. /*    Returns:  True if the ray intersects the cylinder.        */
  31. /*                                    */
  32. /*    Note:      In and/or out may be negative indicating the        */
  33. /*          cylinder is located behind the origin of the ray.    */
  34. /*                                    */
  35. /* -------------------------------------------------------------------- */
  36.  
  37. #define HUGE        1.0e21        /* Huge value            */
  38.  
  39.  
  40. boolean intcyl    (raybase,raycos,base,axis,radius,in,out)
  41.  
  42.     Point3        *raybase;    /* Base of the intersection ray */
  43.     Vector3        *raycos;    /* Direction cosines of the ray */
  44.     Point3        *base;        /* Base of the cylinder        */
  45.     Vector3        *axis;        /* Axis of the cylinder        */
  46.     double        radius;        /* Radius of the cylinder    */
  47.     double        *in;        /* Entering distance        */
  48.     double        *out;        /* Leaving distance        */
  49.  
  50. {
  51.     boolean        hit;        /* True if ray intersects cyl    */
  52.     Vector3        RC;        /* Ray base to cylinder base    */
  53.     double        d;        /* Shortest distance between    */
  54.                     /*   the ray and the cylinder    */
  55.     double        t, s;        /* Distances along the ray    */
  56.     Vector3        n, D, O;
  57.     double        ln;
  58. const    double        pinf = HUGE;    /* Positive infinity        */
  59.  
  60.  
  61.     RC.x = raybase->x - base->x;
  62.     RC.y = raybase->y - base->y;
  63.     RC.z = raybase->z - base->z;
  64.     V3Cross (raycos,axis,&n);
  65.  
  66.     if  ( (ln = V3Length (&n)) == 0. ) {    /* ray parallel to cyl    */
  67.         d     = V3Dot (&RC,axis);
  68.         D.x     = RC.x - d*axis->x;
  69.         D.y     = RC.y - d*axis->y;
  70.         D.z     = RC.z - d*axis->z;
  71.         d     = V3Length (&D);
  72.         *in     = -pinf;
  73.         *out =  pinf;
  74.         return (d <= radius);        /* true if ray is in cyl*/
  75.     }
  76.  
  77.     V3Normalize (&n);
  78.     d    = fabs (V3Dot (&RC,&n));        /* shortest distance    */
  79.     hit  = (d <= radius);
  80.  
  81.     if  (hit) {                /* if ray hits cylinder */
  82.         V3Cross (&RC,axis,&O);
  83.         t = - V3Dot (&O,&n) / ln;
  84.         V3Cross (&n,axis,&O);
  85.         V3Normalize (&O);
  86.         s = fabs (sqrt(radius*radius - d*d) / V3Dot (raycos,&O));
  87.         *in     = t - s;            /* entering distance    */
  88.         *out = t + s;            /* exiting  distance    */
  89.     }
  90.  
  91.     return (hit);
  92. }
  93.  
  94.  
  95. /* ---- clipobj - Clip object with plane pair. ------------------------ */
  96. /*                                    */
  97. /*                                    */
  98. /*    Description:                            */
  99. /*        Clipobj clips the supplied infinite object with two        */
  100. /*        (a top and a bottom) bounding planes.            */
  101. /*                                    */
  102. /*    On entry:                            */
  103. /*        raybase = The base point of the intersecting ray.        */
  104. /*        raycos  = The direction cosines of the above ray. (unit)    */
  105. /*        bot        = The normal and perpendicular distance of the    */
  106. /*              bottom plane.                    */
  107. /*        top        = The normal and perpendicular distance of the    */
  108. /*              top plane.                    */
  109. /*        objin   = The entering distance of the intersection with    */
  110. /*              the object.                    */
  111. /*        objout  = The exiting  distance of the intersection with    */
  112. /*              the object.                    */
  113. /*                                    */
  114. /*    On return:                            */
  115. /*        objin   = The entering distance of the intersection.    */
  116. /*        objout  = The exiting  distance of the intersection.    */
  117. /*        surfin  = The identifier for the entering surface.        */
  118. /*        surfout = The identifier for the leaving surface.        */
  119. /*                                    */
  120. /*    Returns:  True if the ray intersects the bounded object.    */
  121. /*                                    */
  122. /* -------------------------------------------------------------------- */
  123.  
  124. #define        SIDE    0        /* Object surface        */
  125. #define        BOT    1        /* Bottom end-cap surface    */
  126. #define        TOP    2        /* Top      end-cap surface    */
  127.  
  128. typedef struct    {            /* Plane: ax + by + cz + d = 0    */
  129.     double    a ,b ,c, d;
  130. }    Plane;
  131.  
  132.  
  133. boolean clipobj        (raybase,raycos,bot,top,objin,objout,surfin,surfout)
  134.  
  135.     Point3        *raybase;    /* Base of the intersection ray */
  136.     Vector3        *raycos;    /* Direction cosines of the ray */
  137.     Plane        *bot;        /* Bottom end-cap plane        */
  138.     Plane        *top;        /* Top end-cap plane        */
  139.     double        *objin;        /* Entering distance        */
  140.     double        *objout;    /* Exiting  distance        */
  141.     int        *surfin;    /* Entering surface identifier    */
  142.     int        *surfout;    /* Exiting  surface identifier    */
  143.  
  144. {
  145.     boolean hit;
  146.     double    dc, dw, t;
  147.     double    in, out;        /* Object  intersection dists.    */
  148.  
  149.     *surfin = *surfout = SIDE;
  150.     in  = *objin;
  151.     out = *objout;
  152.  
  153. /*    Intersect the ray with the bottom end-cap plane.        */
  154.  
  155.     dc = bot->a*raycos->x  + bot->b*raycos->y  + bot->c*raycos->z;
  156.     dw = bot->a*raybase->x + bot->b*raybase->y + bot->c*raybase->z + bot->d;
  157.  
  158.     if  ( dc == 0.0 ) {        /* If parallel to bottom plane    */
  159.         if    ( dw >= 0. ) return (FALSE);
  160.     } else {
  161.         t  = - dw / dc;
  162.         if    ( dc >= 0.0 ) {                /* If far plane    */
  163.         if  ( t > in && t < out ) { out = t; *surfout = BOT; }
  164.         if  ( t < in  ) return (FALSE);
  165.          } else {                    /* If near plane    */
  166.         if  ( t > in && t < out ) { in    = t; *surfin  = BOT; }
  167.         if  ( t > out ) return (FALSE);
  168.         }
  169.     }
  170.  
  171. /*    Intersect the ray with the top end-cap plane.            */
  172.  
  173.     dc = top->a*raycos->x  + top->b*raycos->y  + top->c*raycos->z;
  174.     dw = top->a*raybase->x + top->b*raybase->y + top->c*raybase->z + top->d;
  175.  
  176.     if  ( dc == 0.0 ) {        /* If parallel to top plane    */
  177.         if    ( dw >= 0. ) return (FALSE);
  178.     } else {
  179.         t  = - dw / dc;
  180.         if    ( dc >= 0.0 ) {                /* If far plane    */
  181.         if  ( t > in && t < out ) { out = t; *surfout = TOP; }
  182.         if  ( t < in  ) return (FALSE);
  183.          } else {                    /* If near plane    */
  184.         if  ( t > in && t < out ) { in    = t; *surfin  = TOP; }
  185.         if  ( t > out ) return (FALSE);
  186.         }
  187.     }
  188.  
  189.     *objin    = in;
  190.     *objout = out;
  191.     return (in < out);
  192. }
  193.